View Javadoc

1   // Delegates.java, created Wed Dec 11 12:02:02 2002 by mcmartin
2   // Copyright (C) 2001-3 mcmartin
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
4   package joeq.Class;
5   
6   import java.util.Iterator;
7   import java.util.LinkedList;
8   import java.util.List;
9   import joeq.Allocator.CodeAllocator;
10  import joeq.Allocator.DefaultHeapAllocator;
11  import joeq.Assembler.DirectBindCall;
12  import joeq.Bootstrap.BootstrapCodeAddress;
13  import joeq.Bootstrap.BootstrapHeapAddress;
14  import joeq.Compiler.CompilerInterface;
15  import joeq.Main.jq;
16  import joeq.Memory.CodeAddress;
17  import joeq.Memory.HeapAddress;
18  import joeq.Memory.StackAddress;
19  import joeq.Runtime.Debug;
20  import joeq.Runtime.ExceptionDeliverer;
21  import jwutil.collections.Filter;
22  import jwutil.collections.Pair;
23  
24  /***
25   * Delegates
26   *
27   * @author Michael Martin <mcmartin@stanford.edu>
28   * @version $Id: Delegates.java 1941 2004-09-30 03:37:06Z joewhaley $
29   */
30  public class Delegates implements jq_ClassFileConstants {
31      static class Field implements jq_Field.Delegate {
32          public final boolean isCodeAddressType(jq_Field f) {
33              return f.getType() == CodeAddress._class ||
34                  f.getType() == BootstrapCodeAddress._class;
35          }
36          public final boolean isHeapAddressType(jq_Field f) {
37              return f.getType() == HeapAddress._class ||
38                  f.getType() == BootstrapHeapAddress._class;
39          }
40          public final boolean isStackAddressType(jq_Field f) {
41              return f.getType() == StackAddress._class;
42          }
43      }
44      static class Method implements jq_Method.Delegate {
45          public final jq_CompiledCode compile_stub (jq_Method m) {
46              return default_compiler.generate_compile_stub(m);
47          }
48          public final jq_CompiledCode compile (jq_Method m) {
49              jq_CompiledCode default_compiled_version;
50              //System.out.println("Compiling: "+m);
51              if (m.isNative() && m.getBytecode() == null) {
52                  System.out.println("Unimplemented native method! "+m);
53                  if (ExceptionDeliverer._nativeMethodError.getState() < STATE_CLSINITIALIZED) {
54                      jq_Class k = ExceptionDeliverer._class;
55                      k.verify(); //k.prepare();
56                      if (ExceptionDeliverer._nativeMethodError.getState() != STATE_PREPARED)
57                          ExceptionDeliverer._nativeMethodError.prepare();
58                      default_compiled_version = ExceptionDeliverer._nativeMethodError.compile();
59                      //if (k != getDeclaringClass() && getDeclaringClass().getSuperclass() != null) { k.cls_initialize(); }
60                  } else {
61                      default_compiled_version = ExceptionDeliverer._nativeMethodError.getDefaultCompiledVersion();
62                  }
63              } else if (m.isAbstract()) {
64                  if (ExceptionDeliverer._abstractMethodError.getState() < STATE_CLSINITIALIZED) {
65                      jq_Class k = ExceptionDeliverer._class;
66                      k.verify(); //k.prepare();
67                      //default_compiled_version = x86ReferenceLinker._abstractMethodError.getDefaultCompiledVersion();
68                      if (ExceptionDeliverer._abstractMethodError.getState() != STATE_PREPARED)
69                          ExceptionDeliverer._abstractMethodError.prepare();
70                      default_compiled_version = ExceptionDeliverer._abstractMethodError.compile();
71                      //if (k != getDeclaringClass() && getDeclaringClass().getSuperclass() != null) { k.cls_initialize(); }
72                  } else {
73                      default_compiled_version = ExceptionDeliverer._abstractMethodError.getDefaultCompiledVersion();
74                  }
75              } else {
76                  CompilerInterface compiler = getCompiler(m);
77                  default_compiled_version = compiler.compile(m);
78                  if (jq.RunningNative)
79                      default_compiled_version.patchDirectBindCalls();
80              }
81              return default_compiled_version;
82          }
83      }
84      public static CompilerInterface default_compiler;
85      public static List compilers = new LinkedList();
86      public static CompilerInterface getCompiler(String name) {
87          try {
88              Class c = Class.forName(name);
89              return (CompilerInterface) c.newInstance();
90          } catch (Exception x) {
91              System.err.println("Error occurred while instantiating compiler "+name);
92              x.printStackTrace();
93              return null;
94          }
95      }
96      public static void setDefaultCompiler(String name) {
97          CompilerInterface c = getCompiler(name);
98          if (c == null) c = getCompiler("joeq.Compiler.Reference.x86.x86ReferenceCompiler.Factory");
99          default_compiler = c;
100     }
101     public static void registerCompiler(Filter f, CompilerInterface c) {
102         compilers.add(0, new Pair(f, c));
103     }
104     public static CompilerInterface getCompiler(jq_Method m) {
105         for (Iterator i=compilers.iterator(); i.hasNext(); ) {
106             Pair p = (Pair) i.next();
107             Filter f = (Filter) p.get(0);
108             if (f.isElement(m))
109                 return (CompilerInterface) p.get(1);
110         }
111         return default_compiler;
112     }
113     
114     static class CompiledCode implements jq_CompiledCode.Delegate {
115         public void patchDirectBindCalls (Iterator i) {
116             while (i.hasNext()) {
117                 DirectBindCall r = (DirectBindCall) i.next();
118                 r.patch();
119             }
120         }
121         public void patchDirectBindCalls (Iterator i, jq_Method method, jq_CompiledCode cc) {
122             while (i.hasNext()) {
123                 DirectBindCall r = (DirectBindCall) i.next();
124                 if (r.getTarget() == method) {
125                     if (jq_CompiledCode.TRACE_REDIRECT) Debug.writeln("patching direct bind call in " + this + " at " + r.getSource().stringRep() + " to refer to " + cc);
126                     r.patchTo(cc);
127                 }
128             }
129         }
130         public Iterator getCompiledMethods() {
131             return CodeAllocator.getCompiledMethods();
132         }
133         public final void deliverToStackFrame(Object ed, jq_CompiledCode t, Throwable x, jq_TryCatch tc, CodeAddress entry, StackAddress fp) {
134             ((ExceptionDeliverer)ed).deliverToStackFrame(t, x, tc, entry, fp);
135         }
136         public final Object getThisPointer(Object ed, jq_CompiledCode t, CodeAddress ip, StackAddress fp) {
137             return ((ExceptionDeliverer)ed).getThisPointer(t, ip, fp);
138         }
139     }
140     
141     static class Klass implements jq_Class.Delegate {
142         public final Object newInstance(jq_Class c, int instance_size, Object vtable) {
143             c.cls_initialize();
144             return DefaultHeapAllocator.allocateObject(instance_size, vtable);
145         }
146     }
147     static class Array implements jq_Array.Delegate {
148         public final Object newInstance(jq_Array a, int length, Object vtable) {
149             return DefaultHeapAllocator.allocateArray(length, a.getInstanceSize(length), vtable);
150         }
151     }
152 }